<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>SendPkt快速入门</title>
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $
:Revision: $Revision: 4224 $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

tt.docutils {
  background-color: #eeeeee }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="sendpkt">
<h1 class="title">SendPkt快速入门</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">作者:</th><td class="field-body">gashero</td>
</tr>
<tr class="field"><th class="docinfo-name">电邮:</th><td class="field-body"><a class="reference" href="mailto:harry.python&#64;gmail.com">harry.python&#64;gmail.com</a></td>
</tr>
<tr class="field"><th class="docinfo-name">原文地址:</th><td class="field-body"><a class="reference" href="http://gashero.yeax.com/?p=26">http://gashero.yeax.com/?p=26</a></td>
</tr>
<tr class="field"><th class="docinfo-name">项目主页:</th><td class="field-body"><a class="reference" href="http://sendpkt.googlecode.com">http://sendpkt.googlecode.com</a></td>
</tr>
<tr class="field"><th class="docinfo-name">日期:</th><td class="field-body">2007-10-03</td>
</tr>
<tr class="field"><th class="docinfo-name">版本:</th><td class="field-body">sendpkt 0.2</td>
</tr>
<tr class="field"><th class="docinfo-name">修订版:</th><td class="field-body">1</td>
</tr>
</tbody>
</table>
<div class="contents topic">
<p class="topic-title first"><a id="id1" name="id1">目录</a></p>
<ul class="auto-toc simple">
<li><a class="reference" href="#id2" id="id7" name="id7">1&nbsp;&nbsp;&nbsp;简介</a></li>
<li><a class="reference" href="#id4" id="id8" name="id8">2&nbsp;&nbsp;&nbsp;使用SendPkt的流程</a></li>
<li><a class="reference" href="#id5" id="id9" name="id9">3&nbsp;&nbsp;&nbsp;SendPkt发送数据包的简单例子</a></li>
<li><a class="reference" href="#sendpkt-arp" id="id10" name="id10">4&nbsp;&nbsp;&nbsp;SendPkt发送ARP查询包的例子</a></li>
<li><a class="reference" href="#id6" id="id11" name="id11">5&nbsp;&nbsp;&nbsp;参考</a></li>
</ul>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id7" id="id2" name="id2">1&nbsp;&nbsp;&nbsp;简介</a></h1>
<p>摘自 <a class="reference" href="http://sendpkt.googlecode.com/">SendPkt</a> 项目wiki。</p>
<p>SendPkt是一套同时可以运行在Linux/Win32的发送链路层数据包的Python扩展库。</p>
<p>SendPkt在Linux和Win32下实现方式是不同的，但是提供对Python的相同接口，确保Python程序可以不经过修改就可以移植。</p>
<p>在Win32下SendPkt使用WinPcap?中的 <cite>pcap_sendpacket()</cite> 函数发送数据包。</p>
<p>在Linux下SendPkt使用libnet的 <cite>libnet_adv_write_link()</cite> 函数发送数据包。</p>
<p>同时SendPkt还提供了查找网络接口设备的功能，以供发送数据包时选择。在Linux下虽然可以使用libnet自动选择的网络接口设备，但是在Win32下，默认的网络设备总会导致发包失败。所以为了可移植性，你必须在发送数据包时指定使用哪个网络设备接口。</p>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id8" id="id4" name="id4">2&nbsp;&nbsp;&nbsp;使用SendPkt的流程</a></h1>
<ol class="arabic">
<li><p class="first">选择合适的网络接口以发送数据包，因为Win32于Linux的不同，需要专门选择。</p>
<blockquote>
<p>对于Win32，通过libpcap取得的第一个网络设备接口(网卡)是一个虚拟网卡，无法发送数据包，而一般选择第二个网口，可以通过os.name判断操作系统并选择合适的网口。</p>
<p>得到的网络设备接口列表，是一个字符串列表，最终提供给发送函数的网口标志也是字符串。</p>
</blockquote>
</li>
<li><p class="first">构造数据包。推荐使用dpkt。</p>
<blockquote>
<p>dpkt是python界通用的数据包组包和解包库，在分层构造数据包时从高层(应用层)向底层依次构造数据包。并且把高层数据包的数据作为下一层数据包的data字段来使用。</p>
<p>对于高性能应用，手工构造数据包也未尝不可，因为哪种方式都需要对数据包格式的深入了解。</p>
</blockquote>
</li>
<li><p class="first">发送数据包，使用 <cite>sendpkt.sendpacket()</cite> 。</p>
<blockquote>
<p>例子见下面的代码。调用方式为 <tt class="docutils literal"><span class="pre">sendpkt.sendpacket(packet,device)</span></tt> 。第一个参数为数据包，为字符串对象，以太网帧。第二个参数为网络设备名，通过第一步获得。</p>
</blockquote>
</li>
</ol>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id9" id="id5" name="id5">3&nbsp;&nbsp;&nbsp;SendPkt发送数据包的简单例子</a></h1>
<p>参见SendPkt项目的单元测试 <tt class="docutils literal"><span class="pre">test.py</span></tt> 。:</p>
<pre class="literal-block">
import sendpkt
#构造一个需要发送的数据包
packet=&quot;a&quot;*80
#查找所有可用网络设备接口
devlist=sendpkt.findalldevs()
#根据操作系统选择合适的网络设备
if devlist:
    if os.name==&quot;nt&quot;:
        device=devlist[-1] #\\NPF\\....
    elif os.name==&quot;posix&quot;:
        device=devlist[0] #eth0
    else:
        device=devlist[0]
else:
    device=&quot;&quot;
    raise OSError,&quot;You must run in root mode&quot;
#发送数据包
sendpkt.sendpacket(packet,device)
</pre>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id10" id="sendpkt-arp" name="sendpkt-arp">4&nbsp;&nbsp;&nbsp;SendPkt发送ARP查询包的例子</a></h1>
<p>ARP查询包的op字段为1，表示查询一个IP地址对应的MAC地址。如下是查询过程。:</p>
<pre class="literal-block">
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
# File: arpquery.py
# Date: 2007-09-21
# Author: gashero
# Copyright&#64;1999-2007, Harry Gashero Liu.

&quot;&quot;&quot;
ARP查询的测试
&quot;&quot;&quot;

from socket import inet_aton,inet_ntoa

import dpkt
import sendpkt

LOCALMAC=&quot;111111&quot;
LOCALIP=inet_aton(&quot;192.168.1.104&quot;)
REMOTEMAC=&quot;&quot;
REMOTEIP=inet_aton(&quot;192.168.1.1&quot;)

def main():
    global LOCALMAC
    global LOCALIP
    device=sendpkt.findalldevs()[0] #for linux is eth0
    arp=dpkt.arp.ARP(
            hrd=1,
            pro=2048,
            hln=6,
            pln=4,
            op=1,
            sha=LOCALMAC,
            spa=LOCALIP,
            tha=&quot;\x00&quot;*6,
            tpa=inet_aton(&quot;192.168.1.1&quot;)
            )
    ether=dpkt.ethernet.Ethernet(
            dst=&quot;\xff&quot;*6,
            src=LOCALMAC,
            type=0x0806,
            data=arp
            )
    #print ether
    #print repr(dpkt.ethernet.Ethernet(str(ether)))
    sendpkt.sendpacket(str(ether),device)
    return

if __name__==&quot;__main__&quot;:
    main()
</pre>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id11" id="id6" name="id6">5&nbsp;&nbsp;&nbsp;参考</a></h1>
<p>详细问题请发邮件到 <a class="reference" href="mailto:harry.python&#64;gmail.com">harry.python&#64;gmail.com</a> 询问。</p>
</div>
</div>
</body>
</html>
